﻿using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.Linq;
using System.Web.Mvc;
using XRM.Security.DataAccess.Enums;
using XRM.Security.DataAccess.Helpers;
using XRM.Security.DataAccess.Interfaces;
using db = XRM.Security.DataAccess.Models;

namespace XRM.Security.WebUI.Models.CertRegister
{
    public class CertRegisterListModel : BaseViewModel
    {
        [Display(Name = "Поиск")]
        public string TextFilter { get; set; }
        [Display(Name = "Искать среди недействующих")]
        public bool ShowAllFilter { get; set; }
        [Display(Name = "Срок истечения менее чем")]
        [Range(0, int.MaxValue, ErrorMessage = "Поле 'Количество дней' должно быть больше нуля")]
        [RegularExpression(@"[0-9]{1,10}", ErrorMessage = "Поле 'Количество дней' не является числом")]
        public int? ExpireDayFilter { get; set; }

        public List<CertSearchItem> CertList { get; set; }
    }

    public class CertRegisterModel : BaseViewModel, IValidatableObject, IUserCertStatus
    {
        public CertRegisterModel()
        {
            UserStatus = (int)DataAccess.Enums.UserStatus.Work;
            SelectedInfoSystems = new List<int>();
        }

        public CertRegisterModel(db.CertRegister dbEntity)
        {
            Id = dbEntity.CertRegisterId;
                
            UserRegisterId = dbEntity.UserRegisterId;
            PCId = dbEntity.PCId;
            FromDate = dbEntity.FromDate;
            ToDate = dbEntity.ToDate;

            if (dbEntity.UserRegister != null)
            {
                UserStatus = dbEntity.UserRegister.Status;
                UserName = dbEntity.UserRegister.FullName();
            }

            SerialNumber = dbEntity.SerialNumber;
            SerialNumberEtoken = dbEntity.SerialNumberEtoken;

            SelectedInfoSystems = dbEntity.CertRegisterInfoSystems.Select( s => s.InfoSystemId ).ToList();
            if (dbEntity.IdentityCenter != null)
                IdentityCenterName = dbEntity.IdentityCenter.IdentityCenterName;

            if (dbEntity.PC != null)
                PCSerialNumber = dbEntity.PC.SerialNumber;
        }

        public CertRegisterModel( db.RequestCert dbEntity )
        {
            if (dbEntity != null)
            {
                Id = dbEntity.RequestCertId;
                SerialNumber = dbEntity.SerialNumber;
                FromDate = dbEntity.FromDate;
                ToDate = dbEntity.ToDate;
                IdentityCenterName = dbEntity.IdentityCenter.IdentityCenterName;
                if (dbEntity.PC != null)
                    PCSerialNumber = dbEntity.PC.SerialNumber;
            }
        }

        public string PCSerialNumber
        {
            get; set;
        }

        [Display(Name = "Пользователь")]
        [Required(ErrorMessage = "Поле 'Пользователь' обязательное")]
        public int? UserRegisterId { get; set; }
        
        [Display(Name = "Серийный номер ПК")]
        public int? PCId { get; set; }
        
        [Display(Name = "Серийный номер сертификата")]
        public string SerialNumber { get; set; }

        [Display(Name = "Серийный номер etoken")]
        [MaxLength(50, ErrorMessage = "Максимальная длина поля 'Серийный номер etoken' 50 символов")]
        public string SerialNumberEtoken { get; set; }

        public DateTime FromDate { get; set; }
        public DateTime ToDate { get; set; }
        public int UserStatus { get; private set; }
        public string DataId { get; set; }

        [Display( Name = "Удостоверяющий центр" )]
        [Required( ErrorMessage = "Поле 'Удостоверяющий центр' обязательное", AllowEmptyStrings = false )]
        public string IdentityCenterName { get; set; }

        public string UserName { get; set; }
        public string CertificateUserName { get; set; }

        [Display(Name = "Срок действия")]
        public string ValidPeriod 
        {
            get
            {
                return FromDate.ToString("dd.MM.yyyy") + " - " + ToDate.ToString("dd.MM.yyyy");
            }
        }
      
        [Display(Name = "Информационные системы")]
        public List<int> SelectedInfoSystems { get; set; }
        public List<SelectListItem> UserInfoSystems { get; set; }
        
        public bool IsFromUser { get; set; }
        public bool ReadOnly
        {
            get { return this.Status() == CertStatus.NotValid; }
        }

        public List<SelectListItem> UserPCList { get; set; }

        public string ReturnUrl
        {
            get; set;
        }

        public IEnumerable<ValidationResult> Validate(ValidationContext validationContext)
        {
            if (SelectedInfoSystems.Distinct().Count() != SelectedInfoSystems.Count())
                yield return new ValidationResult( "Выбранные информационные системы не уникальны", new[] { "SelectedInfoSystems" } );
        }

        public void ApplyChanges( db.CertRegister cert )
        {
            cert.UserRegisterId = UserRegisterId.Value;
            cert.PCId = PCId;
            cert.SerialNumberEtoken = SerialNumberEtoken;
            cert.CertRegisterInfoSystems = SelectedInfoSystems.Select( s => new db.CertRegisterInfoSystem {InfoSystemId = s}).ToList();
        }

        public bool ValidateUser(db.UserRegister user, ModelStateDictionary modelState)
        {
            if ( user == null || user.Status != (int)DataAccess.Enums.UserStatus.Work )
            {
                modelState.AddModelError( "UserRegisterId", "Пользователь должен иметь статус 'Работающий'" );
                return false;
            }
            if (PCId.HasValue && user.PCs.All(s => s.PCId != PCId))
            {
                modelState.AddModelError( "PCId", "Системный блок не найден" );
            }
            //Корректируем коллекцию информационных систем, если на момент сохранения к какой-то из систем уже нет доступа
            if ( SelectedInfoSystems != null )
            {
                SelectedInfoSystems = SelectedInfoSystems.Where( s => UserInfoSystems.Any( t => t.Value == s.ToString() ) ).ToList();
            }
            return true;
        }
    }
}